#include "KmerCounter.h"
#include <ctime>
#include <iostream>

template<> KmerCounter::CounterMap::map_t::BaseClass::pool_type KmerCounter::CounterMap::map_t::BaseClass::_pool
= KmerCounter::CounterMap::map_t::BaseClass::pool_type();

KmerCounter::KmerCounter(AbstractReader& reader, int threshold)
	: verbose(true), m_threshold(threshold), m_trustedCnt(0)
{
	cout <<"Begin to estimate memory consumption..." <<endl;
	//m_allKmers.set_deleted_key((CompressedKmer)0);
	reader.reset();
	GCOUNT_T readNum = reader.getReadCount();
	clock_t DiskTimeElapse=0;
	clock_t AnalyTimeElapse=0;
	clock_t NowTime;
	clock_t StartTime = clock();
	CompressedKmer kmer;
	CompressedKmer rkmer;
	CounterMap::iterator mapiter;
	if (verbose)
	{
		cout<<"having found "<<readNum<<" sequences"<<endl;
	}
	for (GCOUNT_T  i = 0; i < readNum; ++i)
	{
		NowTime = clock();
		char* buffer = reader.getRead();
		DiskTimeElapse += (clock()-NowTime);
		int readLen = strlen(buffer);
		if (readLen < KmerVertex::getLength())
			continue;

		GID_T readID = reader.getID();
		if (!(readID % 10000)) {
			if (verbose)
			{
				cout << "Having read " << readID << " reads." <<endl;
			}
		}

		int numKmer = readLen - KmerVertex::getLength() + 1;

		for (int j = 0; j < numKmer; ++j) {
			if (!KmerVertex::checkKmerString(buffer + j)) {
				j += KmerVertex::getLength() - 1;
				continue;
			}
			kmer.compress(buffer + j);
			kmer.reverse(rkmer);
			if ( (mapiter = m_allKmers.find(kmer)) != m_allKmers.end() )
			{
				++(mapiter->second);
				mapiter = m_allKmers.find(rkmer);
				++(mapiter->second);
			}
			else
			{
				//try
				//{
					m_allKmers.insert(CounterMap::value_type(kmer, 1));
					m_allKmers.insert(CounterMap::value_type(rkmer, 1));
				//}
				//catch(bad_alloc &e)
				//{
				//	cerr<<e.what()<<endl;
				//	exit(2);
				//}
			}
		}
		AnalyTimeElapse = clock()-StartTime;
	} // for (GCOUNT_T  i = 0; i < readNum; ++i)
	//cout <<m_allKmers.size() << endl;

	cout <<"Pruning untrusted k-mers..." <<endl;
	IntNoLessThan conditionor(m_threshold);
	m_trustedCnt = m_allKmers.bucketCount(m_trustedCountArray, conditionor);
	
	AnalyTimeElapse=clock()-StartTime;
	if (verbose)
	{
		cout<<"diskTimeElapse:  " << double (DiskTimeElapse) / CLOCKS_PER_SEC <<" seconds" <<endl;
		cout<<"AnalyTimeElapse:  " << double (AnalyTimeElapse) / CLOCKS_PER_SEC <<" seconds" <<endl;
		cout <<"Total K-mer num: " << numOfAllKmers() << endl;
	}
	cout <<"Finish estimate memory consumption." <<endl;
}